`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    15:27:21 04/12/2011 
// Design Name: 
// Module Name:    InstructionFetch 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module InstructionFetch(clk, branchAddr, jumpPC, jumpInstr, doJmp, doBra, PC, instr, reset);

	input clk;
	input [15:0] branchAddr;
	input [3:0] jumpPC;
	input [11:0] jumpInstr;
	input doJmp;
	input doBra;
	input reset;
	output [15:0] PC; //might need to be changed to bidirectial
	output [15:0] instr;
	
	//reg [15:0] PC;
	wire [15:0] combine;
	reg [15:0] muxToMux;
	reg [15:0] muxToPC;
	reg [15:0] outOfPC;
	
	//first mux to determine a jump or not
	always @ (doJmp or PC or combine)
	begin
		if (doJmp)
			muxToMux <= combine;
		else
			muxToMux <= PC;
	end
	
	//second mux after first to determine branch or not
	always @ (doBra or muxToMux or branchAddr)
	begin
		if (doBra)
			muxToPC <= branchAddr;
		else 
			muxToPC <= muxToMux;
	end
	
	//insert code for PC stuffs
	
	//add 1 to the PC
	adder i_adder(
	.a(outOfPC),
	.b(16'h0001),
	.out(PC));
	
	//Instruction memory (what does addr need to be?)
	InstrMem i_InstrMem(
	.clk(clk),
	.addr(outOfPC[7:0]),
	.instr(instr),
	.reset(reset));
	
	assign combine[15:12] = jumpPC;
	assign combine[11:0] = jumpInstr;


endmodule
